#ifndef SERIALPORT_H
#define SERIALPORT_H

#include <QWidget>
#include <QSerialPort>
#include <QString>
#include <QSerialPortInfo>
#include <QMessageBox>
#include <QTimer>
#include <QPainter>
#include <QComboBox>
#include <Qlabel>
#include <QTextEdit>
#include <QMutex>
#include <QSqlDatabase>
#include <src/commom/staticbutton.h>
#include "../commom/basestylewidget.h"
#include <QRunnable>
#include <QVector>
#include <QDebug>
#include <QSqlError>

/**
 * @brief 串口通信和数据库操作的主类
 * 实现串口通信、数据采集和数据库存储功能
 */
class serialPort : public BaseStyleWidget
{
    Q_OBJECT
public:
    explicit serialPort(QWidget *parent = nullptr);
    ~serialPort();
    QSerialPort *serialP;     // 串口对象指针
    //串口名
    QComboBox *cboxPortName;  // 串口选择下拉框
    //波特率
    QComboBox *cboxBaudRate;  // 波特率选择下拉框
    //数据位
    QComboBox *cboxDataBit;   // 数据位选择下拉框
    //校验位
    QComboBox *cboxParity;    // 校验位选择下拉框
    //停止位
    QComboBox *cboxStopBit;   // 停止位选择下拉框
    //串口名
    QLabel *labelPortName;
    //波特率
    QLabel *labelBaudRate;
    //数据位
    QLabel *labelDataBit;
    //校验位
    QLabel *labelParity;
    //停止位
    QLabel *labelStopBit;
    //隐藏用来读取回复的数据
    StaticButton *Button;
    StaticButton *Button2;
    double str_rev;
    QByteArray recBuf;
    QByteArray array;
    QList<QByteArray> byteArrayList;
    QVector<double> currentData; // 存储一轮采集的数据

    bool isSignalConnected;    // 信号连接状态标志
    QTimer mDataTimer;         // 定时器,用于定期发送命令
    int cs=1;                  // 当前命令索引
    QMutex csMutex;           // 互斥锁,保护cs变量
    QSqlDatabase db;          // 数据库连接对象

    void setButton(StaticButton *newButton);

private:
    void initUi();            // 初始化用户界面
    void initDatabase();      // 初始化数据库
    void insertDataToDatabase(); // 数据插入数据库

public slots:
    void on_openBt_clicked();    // 打开串口按钮点击处理
    void on_sendBt_clicked();    // 发送数据按钮点击处理
    void manual_serialPortReadyRead(); // 串口数据接收处理
    double processData(const QByteArray &data); // 数据解析处理
    void timerSlot();         // 定时器触发处理

signals:
    void mySignal(double value); // 定义一个带有参数的信号
    void mySignal2(double value); // 定义一个带有参数的信号
    void mySignal3(double value); // 定义一个带有参数的信号
    void mySignal4(double value); // 定义一个带有参数的信号
    void mySignal5(double value); // 定义一个带有参数的信号
    void mySignal6(double value); // 定义一个带有参数的信号
    void mySignal7(double value); // 定义一个带有参数的信号
    void mySignal8(double value); // 定义一个带有参数的信号
    void mySignal9(double value); // 定义一个带有参数的信号
    void mySignal10(double value); // 定义一个带有参数的信号
};

#include <QRunnable>
#include <QSqlQuery>
#include <QVector>
#include <QCoreApplication>
#include <QElapsedTimer>
#include <QRandomGenerator>
#include <QDateTime>

/**
 * @brief 数据库插入任务类
 * 在独立线程中执行数据库插入操作
 */
class DatabaseInsertTask : public QRunnable {
public:
    explicit DatabaseInsertTask(const QVector<double>& data)
        : m_data(data) {
        setAutoDelete(true); // 任务完成后自动删除
    }

    void run() override {
        QElapsedTimer timer;
        timer.start();
        QString connectionName = "thread_conn_" + QString::number(reinterpret_cast<quintptr>(this));
        {
            QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
            db.setDatabaseName(qApp->applicationDirPath() + "/testsql.db");
            if (!db.open()) {
                qCritical() << "子线程连接失败：" << db.lastError().text();
                return;
            }

            QSqlQuery query(db);
            query.prepare("INSERT INTO dataconM (时间, NO浓度, NO2浓度, NOx浓度, 流量, 压力, "
                        "反应室温度, 机箱温度, 冷堆温度, 转换炉温度, PMT电压) "
                        "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
            
            // 添加当前时间
            query.addBindValue(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
            
            // 添加其他数据
            for (int i = 0; i < m_data.size(); ++i) {
                query.addBindValue(m_data.at(i));
            }

            if (!query.exec()) {
                qCritical() << "插入失败：" << query.lastError().text();
            }
            
            db.close();
        }
        QSqlDatabase::removeDatabase(connectionName); // 清理连接

        qDebug() << "插入耗时：" << timer.elapsed() << "ms";
    }

private:
    QVector<double> m_data; // 待插入的数据
};

/**
 * @brief 数据库压力测试任务类
 * 用于测试数据库的并发插入性能
 */
class DatabaseStressTestTask : public QRunnable {
public:
    explicit DatabaseStressTestTask(int dataSize) : m_dataSize(dataSize) {
        setAutoDelete(true);
    }

    QVector<double> generateMockData(int size) {
        QVector<double> data;
        for (int i = 0; i < size; ++i) {
            data.append(QRandomGenerator::global()->generateDouble() * 100.0);
        }
        return data;
    }

    void run() override {
        QVector<double> data = generateMockData(m_dataSize);
        QString connectionName = "stress_test_" + QString::number(reinterpret_cast<quintptr>(this));
        {   // 使用作用域来确保数据库连接在移除前被正确关闭
            QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
            db.setDatabaseName(qApp->applicationDirPath() + "/testsql.db");
            if (!db.open()) {
                qCritical() << "无法打开数据库：" << db.lastError().text();
                return;
            }

            QSqlQuery query(db);
            query.prepare("INSERT INTO dataconM (时间, NO浓度, NO2浓度, NOx浓度, 流量, 压力, "
                        "反应室温度, 机箱温度, 冷堆温度, 转换炉温度, PMT电压) "
                        "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

            query.addBindValue(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
            
            for (double value : data) {
                query.addBindValue(value);
            }

            QElapsedTimer timer;
            timer.start();
            
            if (!query.exec()) {
                qCritical() << "插入失败：" << query.lastError().text();
            } else {
                qDebug() << "插入耗时：" << timer.elapsed() << "ms";
            }
            
            query.finish();  // 确保查询完成
            db.close();
        }
        QSqlDatabase::removeDatabase(connectionName);
    }

private:
    int m_dataSize;
};

#endif // SERIALPORT_H
